`include "define.sv"

module sync_fifo_B #(
    parameter DATA_WIDTH = `DATA_WIDTH,  // 使用宏定义数据位宽
    parameter DEPTH      = 512           // 深度需≥最大矩阵元素数
)(
    input                       clk,
    input                       reset,
    input         [1:0]         matrix_type,  // 矩阵类型输入端口
    input                       wr_en,
    input                       rd_en,
    input      [DATA_WIDTH-1:0] din,
    output reg [DATA_WIDTH-1:0] dout,
    output                      full,
    output reg                  done,
    output reg                  empty
);

// ========== 存储与指针定义 ==========
localparam PTR_WIDTH = $clog2(DEPTH);
reg [PTR_WIDTH:0] cnt;               // 计数器[0~DEPTH]
reg [DATA_WIDTH-1:0] mem[0:DEPTH-1]; // 存储阵列
reg [PTR_WIDTH-1:0] wr_ptr, rd_ptr;  // 行优先指针

// ========== 矩阵大小解码逻辑 ==========
reg [PTR_WIDTH:0] matrix_size; // 当前矩阵总元素数
always @(*) begin
    case(matrix_type)
        `m16n16k16: matrix_size = 256; // 16x16
        `m32n8k16:  matrix_size = 128; // 16*8
        `m8n32k16:  matrix_size = 512; // 16*32
        default:    matrix_size = 0;
    endcase
end

// ========== 转置地址生成优化 ==========
reg [PTR_WIDTH-1:0] transposed_rd_addr; // 改为reg类型

always @(*) begin  // 组合逻辑
    case(matrix_type)
        `m16n16k16: begin  // 16x16矩阵：交换高/低4位
            transposed_rd_addr = {rd_ptr[3:0], rd_ptr[7:4]};
        end
        `m32n8k16: begin   // 32x8矩阵：低3位列号+高5位行号
            transposed_rd_addr = {rd_ptr[2:0], rd_ptr[7:3]};
        end
        `m8n32k16: begin   // 8x32矩阵：低5位列号+高3位行号
            transposed_rd_addr = {rd_ptr[4:0], rd_ptr[7:5]};
        end
        default: transposed_rd_addr = rd_ptr; // Fallback
    endcase
end

// ========== 转置计数器逻辑 ==========
reg [PTR_WIDTH:0] transposed_cnt; // 已转置元素计数
always @(posedge clk) begin
    if (reset) begin
        transposed_cnt <= 0;
    end else if (rd_en && !empty) begin
        // 达到最大值时归零，否则递增
        transposed_cnt <= (transposed_cnt == matrix_size - 1) ? 0 : transposed_cnt + 1;
    end
    else begin
        transposed_cnt <= 0;
    end
end

always @(posedge clk or posedge reset) begin
    if (reset) begin
        done <= 0;
    end else begin
        // 当完成最后一个元素转置时，下一周期拉高done
        done <= (!empty && (transposed_cnt == matrix_size - 1));
    end
end

// ========== 主控制逻辑（保持原样） ==========
always @(posedge clk) begin
    if (reset) begin
        wr_ptr <= '0;
        rd_ptr <= '0;
        cnt <= '0;
        dout <= '0;
        foreach (mem[i]) mem[i] <= '0;
    end else begin
        // 写操作：行优先存储
        if (wr_en && !full) begin
            mem[wr_ptr] <= din;
            wr_ptr <= wr_ptr + 1'b1;
        end
        
        // 读操作：转置输出
        if (rd_en && !empty) begin
            dout <= mem[transposed_rd_addr];
            rd_ptr <= rd_ptr + 1'b1;
        end
        
        // 计数器更新（支持动态矩阵类型）
        case ({wr_en, rd_en})
            2'b00: cnt <= cnt;        // 无操作
            2'b01: cnt <= cnt - 1'b1; // 仅读
            2'b10: cnt <= cnt + 1'b1; // 仅写
            2'b11: cnt <= cnt;        // 同时读写
        endcase
    end
end

// ========== 空满信号生成（保持原样） ==========
assign full = (cnt == DEPTH);  // 标准满信号
always @(*) begin              // 空信号优化
    empty = (cnt == 0);        // 直接计数器判断
end

endmodule